/**
  * Copyright (c) CSIRO Australia, 2009
  *
  * @author $Author: jia020 $
  * @version $Id: TimerThread.java 643 2009-05-20 00:20:55Z jia020 $
  */
package au.csiro.nt.pdsp.workflow;

import java.security.Security;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Calendar;
import java.util.logging.Level;
import java.util.logging.FileHandler;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import javax.mail.MessagingException;

import au.csiro.nt.pdsp.accesscontrol.AccessController;
import au.csiro.nt.pdsp.client.PdspConst;
import au.csiro.nt.pdsp.util.Config;
import au.csiro.nt.pdsp.util.MySQL;
import au.csiro.nt.pdsp.util.SendMail;
import au.csiro.nt.pdsp.util.Util;

/**
 * A daemon thread class.
 * Monitoring the state of workflow.
 * Processing workflow based on the state.
 * Monitoring the state of Message
 * Processing the message basedon the state.
 * @author jia020
 */

public class TimerThread implements Runnable {
	private boolean bWantToStop = false;
	private Thread thread;
	private AccessController accessController = null;
	public TimerThread() {
		thread = new Thread(this);
		accessController = new AccessController();
		thread.start();
	}

	@Override
	public String toString() {
		return "#TimerThread";
	}

	public boolean start() {
		bWantToStop = false;
		return true;
	}

	public void stop() {
		bWantToStop = true;
		return;
	}
//	private String ContentXACMLFilter(String original) {
//		//FIXME:Policy control and content filtering
//
//		String filtered = accessController.contentFiltering(original);
//		return filtered;
//	}
	@Override
	public void run() {
		System.out.println(this);
		Logger logger = Logger.getLogger("TimerThread");
		FileHandler fh;
		try {
			fh = new FileHandler("mylog.txt");
			fh.setFormatter(new SimpleFormatter());
			logger.addHandler(fh);
			logger.setLevel(Level.ALL);
		} catch (Exception ex) {
			ex.printStackTrace();
		}

		logger.warning("start");

		String sSql = "";
		int workflowid;
		String status;
		String description;
		String organisationuserid;
		String individualuserid;
		String originaldataset;
		String filtereddataset;
		Date createtime;
		Date endtime;
		String emailto;
		String recvmessage;
		Date recvtime;

		MySQL mysql = new MySQL(Config.getInstance().DB_USER,
				Config.getInstance().DB_PIN, Config.getInstance().DB_JDBC);
		MySQL mysql2 = new MySQL(Config.getInstance().DB_USER,
				Config.getInstance().DB_PIN, Config.getInstance().DB_JDBC);
		int cc = 0;
		String sql2 = null;
		PreparedStatement ps = null;
		ResultSet rsSearch = null;
		while (!bWantToStop) {
			try {
				//FIXME:USERS TABLE IS NOT CORRECT.
				//Retrieve the workflows which was just reviewed by administrator.
				sSql = "select w.workflowid,w.status,w.createtime,w.endtime,w.originaldataset,u.email,t.description,w.individualuserid,w.organisationuserid from workflow w,users u,task t where t.taskid = w.taskid and w.status='reviewed' and w.individualuserid = u.username";
				rsSearch = mysql.execSelect(sSql);
				if (rsSearch == null)
					break;
				while (rsSearch.next()) {
					workflowid = rsSearch.getInt("workflowid");
					status = rsSearch.getString("status");
					createtime = rsSearch.getDate("createtime");
					endtime = rsSearch.getDate("endtime");
					emailto = rsSearch.getString("email");		
					originaldataset = rsSearch.getString("originaldataset");
					description = rsSearch.getString("description");
					organisationuserid = rsSearch.getString("organisationuserid");
					individualuserid = rsSearch.getString("individualuserid");			
					//XACML content filtering
					filtereddataset = accessController.contentFiltering(originaldataset);
					sql2 = "update workflow set filtereddataset=? where workflowid=?";
					ps = mysql2.getConnection().prepareStatement(sql2);					
					ps.setString(1, filtereddataset);	
					ps.setInt(2, workflowid);	
					ps.execute();		
					ps.close();
					ps = null;
					//Set workflow status to filtered
					Config.getInstance().pdspLogger.logWorkflow(0, workflowid, PdspConst.WF_STATUS_FILTERED,PdspConst.WF_STATUS_FILTERED + ":SYSTEM");				
					//IMS sending
					String emailMsgTxt = "Dear " + individualuserid + ":\nPrivacy data Requested from " + organisationuserid + "\nRequest Description:\n " + description +"\nPlease authorize to release your privacy data. \n To do that, please follow the link " +
									Config.getInstance().URL_MESSAGE_LINK + "\n Administrator\nCentrelink\n";
					String emailSubjectTxt = "please authorize to release your privacy data. ";
					String emailFrom = "pdspadmin@gmail.com";
					String[] sendTo = { emailto };
					Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
					SendMail.sendSSLMessage(sendTo, emailSubjectTxt, emailMsgTxt,	emailFrom);
					System.out.println("Sucessfully Sent mail to All Users");
					//Set workflow status to pending
					Config.getInstance().pdspLogger.logWorkflow(0, workflowid, PdspConst.WF_STATUS_PENDING,PdspConst.WF_STATUS_PENDING + ":SYSTEM");					
					//Update ims table for the workflow.
					sql2 = "insert into ims(workflowid,mobilefrom,mobileto,callback,sentmessage,senttime) values (?,?,?,?,?,?)";
					ps = mysql2.getConnection().prepareStatement(sql2);
					ps.setInt(1, workflowid);
					ps.setString(2, emailFrom);	
					ps.setString(3, emailto);	
					ps.setString(4, "callback");	
					ps.setString(5, emailMsgTxt);	
					ps.setDate(6, new java.sql.Date(new java.util.Date().getTime()));	
					ps.execute();		
					ps.close();
					ps = null;	
					Config.getInstance().pdspLogger.logIMS(0, workflowid, PdspConst.IMS_STATUS_SENT);							
				}
				rsSearch.close();
				rsSearch = null;
				//Checking the incoming message(authorisation from individual user)
				sSql = "select workflowid,recvmessage,recvtime from ims where status='" + PdspConst.IMS_STATUS_RECV + "'";
				rsSearch = mysql.execSelect(sSql);
				if (rsSearch == null)
					break;
				while (rsSearch.next()) {
					workflowid = rsSearch.getInt("workflowid");
					recvmessage = rsSearch.getString("recvmessage");
					if (recvmessage.equalsIgnoreCase(PdspConst.WF_STATUS_AUTHORIZED)) {
						status = PdspConst.WF_STATUS_AUTHORIZED;
					} else {
						status = PdspConst.WF_STATUS_REJECTED;
					}
					//Set workflow status to filtered
					Config.getInstance().pdspLogger.logWorkflow(0, workflowid, status,status + ":SYSTEM");							
					//Set message status to close
					Config.getInstance().pdspLogger.logIMS(0, workflowid, PdspConst.IMS_STATUS_CLOSE);		
				}
				rsSearch.close();
				rsSearch = null;
				
				//Sleep 5 seconds
				//System.out.println(cc++);
				logger.info(Integer.toString(cc));
				Thread.sleep(5000);
			} catch (MessagingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (Exception e) {
				logger.warning(e.toString());
				e.printStackTrace();
				break;
			}
		}
		logger.warning("end");
	}

	public static void main(String[] args) {
		TimerThread bt = new TimerThread();
		//bt.stop();
		new Thread(bt).start();
	}
}